/**
 * com.chaeron.GPS - An API for access to GPS devices.
 *
 *
 * Copyright (c) 2001, 2002 Chaeron Corporation,
 * All rights reserved.
 * 
 * Chaeron grants you a non-exclusive license to use, modify and re-distribute
 * this program under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version, provided that this copyright notice and 
 * license appear on all copies of the software.
 * 
 * Software is provided "AS IS," without a warranty of any kind. ALL EXPRESS OR
 * IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
 * HEREBY EXCLUDED. THE ENTIRE RISK ARISING OUT OF USING THE SOFTWARE IS ASSUMED
 * BY THE LICENSEE. See the GNU General Public License for more details.
 *
 * CHAERON AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR DISTRIBUTING SOFTWARE.
 * IN NO EVENT WILL CHAERON OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE,
 * PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL
 * OR PUNITIVE DAMAGES, HOWEVER CAUSED AN REGARDLESS OF THE THEORY OF LIABILITY,
 * ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF CHAERON HAS
 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 * @version     1.02
 * @author      Andrzej Jan Taramina, Chaeron Corporation
 *              andrzej@chaeron.com
 */

package com.chaeron.GPS.NMEA;

//***************************************************************************
//*
//*     Imports
//*
//***************************************************************************/

import com.chaeron.GPS.*;
import com.chaeron.GPS.event.*;
import com.chaeron.GPS.exception.*;

//***************************************************************************
//*
//*     GSVSentence Class definition
//*
//***************************************************************************/

/**
 * The GSVSentence class represents NMEA GSV - Satellites in View
 *
 */

public class GSVSentence extends NMEASentence implements GPSSatellitesInView
{
	//***************************************************************************
	//*
	//*     Constant definitions
	//*
	//***************************************************************************/
	
	private final static int		GSV_NUM_FIELDS				= 3;
	
	
	//***************************************************************************
	//*
	//*     Attributes
	//*
	//***************************************************************************/
	
	private int			satellites					= 0;
	
	private short		msgCount					= 0;
	private short		msgNumber					= 0;
	private short		inView						= 0;
	private short[]		number						= null;
	private short[]		elevation					= null;
	private short[]		azimuth						= null;
	private short[]		snr							= null;
	
	
	//***************************************************************************
	//*
	//*     Constructors
	//*
	//***************************************************************************/
	
	/**
	 * Create a GSVSentence from the given packet data
	 *
	 * @param	tid			talker ID
	 * @param	sid			Sentence ID
	 * @param	sentenceStr	sentence string buffer
	 */
	
	GSVSentence( int tid, int sid, String sentenceStr )
	{  
		super( tid, sid, sentenceStr );
		
		setFieldCount( GSV_NUM_FIELDS );
	}
	
	
	//***************************************************************************
	//*
	//*     Methods
	//*
	//***************************************************************************/
	
	/**
	 * Decode the data fields for a GSV sentence
	 *
	 * @return		This method will return a standard error code or GPS.ERROR_OK
	 * @throws GPSPacketException
	 * @throws GPSFunctionUnavailableException
	 */
	
	public void parseData() throws GPSPacketException, GPSFunctionUnavailableException
	{ 
		int		i;
		
		satellites = ( getFieldCount() - 3 ) / 4;
		
		if( getFieldCount() > GSV_NUM_FIELDS && satellites > 0 && ( ( getFieldCount() - 3 ) % 4 ) == 0 ) {
			msgCount			= getNMEAShort( getField( 0 ) );		// Total Message Count
			msgNumber			= getNMEAShort( getField( 1 ) );		// Message Number
			inView				= getNMEAShort( getField( 2 ) );		// Satellites in view
			
			number 		= new short[ satellites ];
			elevation 	= new short[ satellites ];
			azimuth 	= new short[ satellites ];
			snr 		= new short[ satellites ];
			
			for( i = 0; i < satellites; i++ ) {
				number[ i ] 	= getNMEAShort( getField( i*4 + 3 ) );		// Satellite #
				elevation[ i ] 	= getNMEAShort( getField( i*4 + 4 ) );		// Elevation in degrees
				azimuth[ i ] 	= getNMEAShort( getField( i*4 + 5 ) );		// Azimuth in degrees to true
				snr[ i ] 		= getNMEAShort( getField( i*4 + 6 ) );		// SNR in dB
			}
		} else {
			throw( new GPSPacketException( GPSPacketException.EXCEPTION_NUMFIELDS_INVALID ) );
		}
	}
	
	
	//***************************************************************************
	//*
	//*     Sentence Processing Methods
	//*
	//***************************************************************************/
	
	/**
	 * Process the sentence
	 *
	 * @param	gps			the GPS object that requested the GSV sentence to be processed
	 */
	
	void process( GPS gps )
	{
		gps.postGPSEvent( new GPSEvent( GPSEvent.GPS_EVENT_SATELLITES_INVIEW, this ) );
	}
	
	
	/**
	 * Get events generated.
	 *
	 * @return		return a valid event type(s) that will be generated by this sentence subclass
	 */
	
	static int getEventsGenerated()
	{  
		return( GPSEvent.GPS_EVENT_SATELLITES_INVIEW | GPSEvent.GPS_EVENT_NMEA_SENTENCE );
	}
	
	
	//***************************************************************************
	//*
	//*    Accessor methods
	//*
	//***************************************************************************/
	
	/**
	 * Get the Message Count
	 *
	 * @return		Message Count
	 */
	
	public short getMessageCount()
	{  
		return( msgCount );
	}
	
	
	/**
	 * Get the Message Number
	 *
	 * @return		Message Number
	 */
	
	public short getMessageNumber()
	{  
		return( msgNumber );
	}
	
	/**
	 * Get number of satellites in view
	 *
	 * @return	 number of satellites in view
	 */
	
	public int getSatellitesInViewCount()
	{  
		return( inView );
	}
	
	
	/**
	 * Get number of satellites
	 *
	 * @return	 number of satellites
	 */
	
	public int getSatelliteCount()
	{  
		return( satellites );
	}
	
	
	/**
	 * Get the specified satellite number
	 *
	 * @param	index	index of satellite
	 * @return			satellite number
	 */
	
	public short getSatelliteNumber( int index )
	{  
		short		value = -1;
		
		if( index >= 0 && index < satellites ) {
			value = number[ index ];
		}
		
		return( value );
	}
	
	
	/**
	 * Get the specified satellite elevation (in meters)
	 *
	 * @param	index	index of satellite
	 * @return			satellite elevation (in meters)
	 */
	
	public short getElevation( int index )
	{  
		short		value = -1;
		
		if( index >= 0 && index < satellites ) {
			value = elevation[ index ];
		}
		
		return( value );
	}
	
	
	/**
	 * Get the specified satellite azimuth (in meters to true)
	 *
	 * @param	index	index of satellite
	 * @return			satellite azimuth (in meters to true)
	 */
	
	public short getAzimuth( int index )
	{  
		short		value = -1;
		
		if( index >= 0 && index < satellites ) {
			value = azimuth[ index ];
		}
		
		return( value );
	}
	
	
	/**
	 * Get the specified satellite SNR (in dB)
	 *
	 * @param	index	index of satellite
	 * @return			satellite SNR (in db)
	 */
	
	public short getSNR( int index )
	{  
		short		value = -1;
		
		if( index >= 0 && index < satellites ) {
			value = snr[ index ];
		}
		
		return( value );
	}
	
	
	/**
	 * Get extra field count.  Always returns zero for this Sentence type
	 *
	 * @return		zero
	 */
	
	public int getExtraFieldCount()
	{  
		return( 0 );
	}
	
}
